﻿using System.IO;
using System.Text;
using KSS.Generator.Configuration;
using KSS.Generator.Schema;

namespace KSS.Generator
{
    public class SqlSchemaProjectGenerator : ProjectGenerator
    {

        public override string ProjectName
        {
            get { return Template.Project.SqlSchemaProjectName; }
        }

        /// <summary>
        /// Generate all special template file
        /// </summary>
        /// <param name="projectConfig"></param>
        /// <param name="templateFile"></param>
        /// <param name="generatedDirectory"></param>
        protected override void GenerateFile(ProjectSetting projectConfig,
                                        FileInfo templateFile,
                                        DirectoryInfo generatedDirectory)
        {
            switch (templateFile.Name)
            {
                case Template.SqlSchemaProject.GeneratedTableSchemaFileName:
                    GenerateTableSchema(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.SqlSchemaProject.CustomTableSchemaFileName:
                    GenerateCustomTableSchema(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.SqlSchemaProject.GeneratedStoreSchemaFileName:
                    GenerateStoreSchema(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.SqlSchemaProject.CustomStoreSchemaFileName:
                    GenerateCustomStoreSchema(projectConfig, templateFile, generatedDirectory);
                    break;
            }
        }

        /// <summary>
        /// Generate table schema file
        /// </summary>
        /// <param name="projectConfig"></param>
        /// <param name="templateFile"></param>
        /// <param name="generatedDirectory"></param>
        private void GenerateTableSchema(ProjectSetting projectConfig,
                                        FileInfo templateFile,
                                        DirectoryInfo generatedDirectory)
        {
            // Get entity template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            string sourceCode = string.Empty;
            StringBuilder sbColumnDeclaration = new StringBuilder();

            // Fill properties to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                #region { Table name custom tag }

                // Get custom property setting for TableName
                projectConfig.SetPropertyValue(Template.SqlSchemaProject.CustomTag_TableName, t.Member);
                #endregion

                #region { Column declaration tag }

                // Clear buffer
                sbColumnDeclaration.Remove(0, sbColumnDeclaration.Length);

                // create property declaration
                foreach (Column c in t.DataType.Columns)
                {
                    // column declaration
                    sbColumnDeclaration.AppendFormat(
                                Template.SqlSchemaProject.Declaration,
                                c.Name,
                                c.Name.Substring(0, 1).ToUpper() + c.Name.Substring(1, c.Name.Length - 1));
                }

                // Find declaration property
                projectConfig.SetPropertyValue(
                                Template.SqlSchemaProject.CustomTag_ColumnDeclaration,
                                sbColumnDeclaration.ToString());
                #endregion

                // Fill property in template
                sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                string generatedFileNameTemplate = GeneratorHelper.GetFileNameFromat(Template.SqlSchemaProject.GeneratedTableSchemaFileName);

                // Write to source file
                string generatedFilePath = generatedDirectory.FullName + "/" + string.Format(generatedFileNameTemplate, t.Member);

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        /// <summary>
        /// Generate custom table schema file
        /// </summary>
        /// <param name="projectConfig"></param>
        /// <param name="templateFile"></param>
        /// <param name="generatedDirectory"></param>
        private void GenerateCustomTableSchema(ProjectSetting projectConfig,
                                            FileInfo templateFile,
                                            DirectoryInfo generatedDirectory)
        {
            // Get entity template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            string sourceCode = string.Empty;
            string fileNameFormat = string.Empty;

            // Fill properties to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                #region { Table name custom tag }

                // Get custom property setting for TableName
                projectConfig.SetPropertyValue(Template.SqlSchemaProject.CustomTag_TableName, t.Member);
                #endregion

                // Fill property in template
                sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Get file name template
                fileNameFormat = GeneratorHelper.GetFileNameFromat(Template.SqlSchemaProject.CustomTableSchemaFileName);

                // Write to source file
                string filePath = generatedDirectory.FullName + "/" + string.Format(fileNameFormat, t.Member);

                GeneratorHelper.WriteToFile(filePath, sourceCode, true);
            }
        }

        /// <summary>
        /// Generate Store procedure schema file
        /// </summary>
        /// <param name="projectConfig"></param>
        /// <param name="templateFile"></param>
        /// <param name="generatedDirectory"></param>
        private void GenerateStoreSchema(ProjectSetting projectConfig,
                                        FileInfo templateFile,
                                        DirectoryInfo generatedDirectory)
        {
            // Get entity template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Fill properties to template
            foreach (Function f in Context.DatabaseSchema.Functions)
            {
                // Store procedure name
                projectConfig.SetPropertyValue(Template.SqlSchemaProject.CustomTag_StoredProcedureName,
                    GeneratorHelper.GetStoredProcedureName(f.Name));

                // Parameter declaration
                StringBuilder sbParameterDeclaration = new StringBuilder();

                foreach (Parameter p in f.Parameters)
                {
                    sbParameterDeclaration.AppendFormat(
                                Template.SqlSchemaProject.ParameterDeclaration,
                                p.Name,
                                GeneratorHelper.GenerateGlobalVariableName(p.Name));
                }

                projectConfig.SetPropertyValue(
                            Template.SqlSchemaProject.CustomTag_ParameterDeclaration,
                            sbParameterDeclaration.ToString());

                // Fill property in template
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                string generatedFileNameTemplate = GeneratorHelper.GetFileNameFromat(Template.SqlSchemaProject.GeneratedStoreSchemaFileName);

                // Write to source file
                string generatedFilePath = generatedDirectory.FullName + "/" + 
                                            string.Format(generatedFileNameTemplate, 
                                            GeneratorHelper.GetStoredProcedureName(f.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        /// <summary>
        /// Generate custom store procedure schema file
        /// </summary>
        /// <param name="projectConfig"></param>
        /// <param name="templateFile"></param>
        /// <param name="generatedDirectory"></param>
        private void GenerateCustomStoreSchema(ProjectSetting projectConfig,
                                            FileInfo templateFile,
                                            DirectoryInfo generatedDirectory)
        {
            // Get entity template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Fill properties to template
            foreach (Function f in Context.DatabaseSchema.Functions)
            {
                // Store procedure name
                projectConfig.SetPropertyValue(Template.SqlSchemaProject.CustomTag_StoredProcedureName,
                    GeneratorHelper.GetStoredProcedureName(f.Name));

                // Fill property in template
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                string generatedFileNameTemplate = GeneratorHelper.GetFileNameFromat(Template.SqlSchemaProject.CustomStoreSchemaFileName);

                // Write to source file
                string generatedFilePath = generatedDirectory.FullName + "/" +
                                            string.Format(generatedFileNameTemplate,
                                            GeneratorHelper.GetStoredProcedureName(f.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode, true);
            }
        }
    }
}